/*
 * 解析南自设备103协议ASDU
 * */

#ifndef NZPARSER_H
#define NZPARSER_H

#include <QString>
#include <vector>
#include <map>
#include <QMap>
#include "NZ/IEC103Type.h"
#include <QThread>
using namespace std;

class NZParser : public QObject
{
    Q_OBJECT

public:
    NZParser();
    virtual ~ NZParser();

    int recvPacketTypeFilter(const QByteArray& packet);  // 对接收的报文进初步行分类过滤, 返回读定值的具体服务类型

    QStringList parseBillInfo(const int replyType, const QByteArray &packet);      // 返回解析的定值有关定值模板数据序列（name，value）

    QMap<QString,QString> getGroupNoWithName(){ return m_groupNoNameMap; }

    QMap<QString, QString> getAboutBillGroupInfo(QString&); // 获取相关组标题信息,通过宏关键字形式过滤

    void clearBillTableBuffer();    // 清除掉保存的组信息

    QMap<QString, BillTableStruct> getBillTableInfo();

public slots:
    void slot_parseBillInfo(const QByteArray &packet);

signals:
    // 2021.05.27 使用多线程的方式来使用解析层
    void signal_parseFinished(QStringList,int);           // parser层解析完后通知 table更新数据
    void sig_getTitleInfoFinished();
    void sig_getBillAreaFinished(QString);     // 在读取完定值区号后选择当前定值区号
    void sig_sureBillAreaFinished();

private:
    bool parseRecvPacket(const QByteArray& pData, int dataLen);

    /*
     * @Desc: 处理接收到的固定长度报文
     * @Param: pData　解析数据开始地址
     * @Param: dataLen　解析数据长度
     * @Return: 解析成功或失败
     */
//    bool parseFixedData(const QString& pData, int dataLen);

    /*
     * @Desc: 处理接收到的可变帧长度报文
     * @Param: pData　解析数据开始地址
     * @Param: dataLen　解析数据长度
     * @Return: 解析成功或失败
     */
    bool parseVariableData(const QString& pData, int dataLen);

    /*
     * @Desc: 处理ASDU10 报文，包括设备回的读定值值描述等可变帧长报文
     * @Para: 报文，报文长度
     * @Return: 解析成功或者失败
     */
    virtual void parseASDU10(const QString& packet, int length);

    QString sendPacket(); // 给tcp 服务端提供报文

    //显示虽有的数据集的value,初始化定值模板各项列表
    void showDataSets(vector<OneDataSetStruct> &dataSets);

    // 通过指定组的中文名来查询组号
    QString findGroupNoByGroupName(const QString &groupName, vector<OneDataSetStruct> &dataSets);

    /*
     * @Desc: 处理接收大的可变帧长报文
     * @Param: 报文数据
     * @Return： 解析成功或者失败
     */
    vector<OneDataSetStruct> parseASDU10AllValue_GDNZ(const QString &packet);
public:
    QStringList parseBillTitles(const QByteArray &packet);     // 同时返回组号和标题
    QStringList parseBillArea(const QByteArray &packet);
    QStringList parseBillValueNames(const QByteArray &packet);
    QStringList parseBillValueUnits(const QByteArray &packet);
    QStringList parseBillDimension(const QByteArray &packet);
    QStringList parseBillDefaultValue(const QByteArray &packet);
    QStringList parseBillRealValue(const QByteArray &packet);
    QStringList parseBillUnkown( );
    QStringList parseBillValueDataTypes(const QByteArray &packet);

    void getBillTitleGroupNo(const QByteArray &packet);     // packet 参数是查询全部租标题的回复，将组号和标题一一对应

    // 获取定值组的组号
    void initialBillValueGroupNo(QMap<QString, QString> &groupNoAndName);

    QStringList m_billValueName;
    QStringList m_billValueMinList;
    QStringList m_billValueMaxList;
    QStringList m_billValueStepList;
    QStringList m_billValueDefaultList;
    QStringList m_billValueCurrList;
    QStringList m_billValueUinitList;

private:
    QString m_clientAddr = "01";
    QString m_rii = "00";   // 返回信息标志可以固定方便操作

    //由读所有组的标题来初始化这些基础信息
    QString m_ybGroup;          // 压板组, 组名包含有关键字“定值”，返回组号16进制字符串
    QString m_deviceSysGroup;      // 系统组
    QStringList m_billValueGroups;   // 全部的定值组类别，在读取全部标题的时候初始化,南瑞继保存在多个定制组

    //在发送第一个命令读全部组的标题后，解析出的全部组的组号和组名信息结果，这个是后续解析对应各组的前提
    QMap<QString, QString> m_groupNoNameMap;

    QMap<QString, BillTableStruct> m_billTablesMap;        // （组号 ， 具体组号信息）
};

#endif // NZPARSER_H
